import pygame
import random
import time


class SnakeGame:
    def __init__(self):
        # 初始化pygame
        pygame.init()

        # 定义颜色
        self.white = (255, 255, 255)
        self.black = (0, 0, 0)
        self.red = (213, 50, 80)  # 普通果实
        self.green = (0, 255, 0)  # 加速果实
        self.blue = (50, 153, 213)  # 减速果实
        self.orange = (255, 165, 0)  # 加长度和分数果实
        self.rainbow = (255, 105, 180)  # 彩色特殊果实
        self.gray = (200, 200, 200)  # 网格线颜色
        self.purple = (128, 0, 128)  # 新增紫色颜色定义

        # 设置显示窗口
        self.grid_size = 25  # 每个格子的大小
        self.grid_count = 25  # 格子数为 25×25
        self.display_width = self.grid_size * self.grid_count  # 窗口宽度
        self.display_height = self.grid_size * self.grid_count  # 窗口高度
        self.dis = pygame.display.set_mode((self.display_width, self.display_height))
        pygame.display.set_caption('贪吃蛇游戏')

        # 设置游戏时钟
        self.clock = pygame.time.Clock()

        # 蛇的大小
        self.snake_block = self.grid_size  # 蛇块大小与格子大小一致

        # 设置字体
        self.font_style = pygame.font.SysFont("bahnschrift", 25)
        self.score_font = pygame.font.SysFont("comicsansms", 35)

    def draw_grid(self):
        """绘制横竖网格线"""
        for x in range(0, self.display_width, self.grid_size):
            pygame.draw.line(self.dis, self.gray, (x, 0), (x, self.display_height))  # 竖线
        for y in range(0, self.display_height, self.grid_size):
            pygame.draw.line(self.dis, self.gray, (0, y), (self.display_width, y))  # 横线

    def your_score(self, score):
        """显示分数在左上角第一行"""
        value = self.score_font.render("Score: " + str(score), True, self.black)
        self.dis.blit(value, [10, 10])  # 第一行显示分数

    def our_snake(self, snake_block, snake_list):
        for x in snake_list:
            pygame.draw.rect(self.dis, self.black, [x[0], x[1], snake_block, snake_block])

    def message(self, msg, color, y_offset=0):
        mesg = self.font_style.render(msg, True, color)
        self.dis.blit(mesg, [self.display_width / 6, self.display_height / 3 + y_offset])

    def generate_food(self, snake_list):
        """随机生成一个果实，避免第一、第二行"""
        while True:
            foodx = round(random.randrange(0, self.display_width - self.snake_block) / self.grid_size) * self.grid_size
            foody = round(random.randrange(2 * self.grid_size, self.display_height - self.snake_block) / self.grid_size) * self.grid_size
            if [foodx, foody] not in snake_list:
                return foodx, foody

    def generate_purple_food(self, snake_list):
        """生成紫色果实，只在边缘生成"""
        while True:
            if random.choice([True, False]):  # 随机选择水平或垂直边缘
                foodx = random.choice([0, self.display_width - self.snake_block])
                foody = round(random.randrange(0, self.display_height - self.snake_block) / self.grid_size) * self.grid_size
            else:
                foodx = round(random.randrange(0, self.display_width - self.snake_block) / self.grid_size) * self.grid_size
                foody = random.choice([0, self.display_height - self.snake_block])
            if [foodx, foody] not in snake_list:
                return foodx, foody

    def handle_purple_food(self, purple_foods, snake_list, normal_foods, x1, y1):
        """处理紫色果实的移动和碰撞逻辑"""
        new_purple_foods = []
        for food in purple_foods:
            fx, fy = food
            prev_fx, prev_fy = fx, fy  # 记录果实的当前位置

            # 移动紫色果实
            if fx < x1:
                fx += self.snake_block
            elif fx > x1:
                fx -= self.snake_block
            if fy < y1:
                fy += self.snake_block
            elif fy > y1:
                fy -= self.snake_block

            # 检查碰撞
            if [fx, fy] == [x1, y1]:  # 碰到蛇头
                if len(snake_list) == 1:  # 如果蛇长度为1，结束游戏
                    return None, True
                else:
                    continue  # 碰到蛇头，果实消失，蛇长度减1
            elif [fx, fy] in snake_list or [fx, fy] in normal_foods:  # 碰到蛇身体或普通果实
                normal_foods.append((prev_fx, prev_fy))  # 在碰撞前的位置生成一个普通果实
                continue

            new_purple_foods.append((fx, fy))  # 更新果实位置

        return new_purple_foods, False

    def game_over_screen(self, score):
        """结束页面"""
        self.dis.fill(self.white)
        self.message("Game Over!", self.red)
        self.message(f"Your Score: {score}", self.black, 30)
        self.message("Press Q to Quit or R to Restart", self.black, 60)
        pygame.display.update()

        while True:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:  # 按 Q 退出游戏
                        pygame.quit()
                        quit()
                    elif event.key == pygame.K_r:  # 按 R 重开游戏
                        self.gameLoop()
                        return

    def pause_game(self):
        """暂停页面"""
        paused = True
        self.dis.fill(self.white)
        self.message("Game Paused", self.red)
        self.message("Press C to Continue, Q to Quit, R to Restart", self.black, 30)
        pygame.display.update()

        while paused:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_c:  # 按 C 继续游戏
                        for i in range(3, 0, -1):  # 倒计时 3 秒
                            self.dis.fill(self.white)
                            self.message(f"Resuming in {i}...", self.green)
                            pygame.display.update()
                            time.sleep(1)
                        paused = False
                    elif event.key == pygame.K_q:  # 按 Q 退出游戏
                        pygame.quit()
                        quit()
                    elif event.key == pygame.K_r:  # 按 R 重开游戏
                        self.gameLoop()
                        return

    def gameLoop(self):
        # 初始化速度
        default_snake_speed = 10  # 默认速度
        snake_speed = default_snake_speed

        game_over = False

        # 初始化蛇的位置（12×12 格子）
        x1 = 12 * self.grid_size
        y1 = 12 * self.grid_size

        # 初始化蛇的移动方向
        x1_change = 0
        y1_change = 0

        # 初始化蛇的身体
        snake_List = [[x1, y1]]  # 蛇的初始位置
        Length_of_snake = 1

        # 初始化普通果实列表
        normal_foods = []  # [(x, y), ...]
        normal_foods.append(self.generate_food(snake_List))  # 添加第一个普通果实

        # 特殊果实列表
        special_foods = []  # [(x, y, type), ...]

        # 加速或减速的持续时间
        speed_timer = 0

        # 记录上次生成特殊果实的分数
        last_special_food_score = 0

        # 计时器
        normal_food_timer = 0  # 控制普通果实生成

        # 紫色果实列表
        purple_foods = []  # [(x, y), ...]

        # 紫色果实生成计时器
        purple_food_timer = 0

        while not game_over:

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    game_over = True
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT and x1_change == 0:
                        x1_change = -self.snake_block
                        y1_change = 0
                    elif event.key == pygame.K_RIGHT and x1_change == 0:
                        x1_change = self.snake_block
                        y1_change = 0
                    elif event.key == pygame.K_UP and y1_change == 0:
                        y1_change = -self.snake_block
                        x1_change = 0
                    elif event.key == pygame.K_DOWN and y1_change == 0:
                        y1_change = self.snake_block
                        x1_change = 0
                    elif event.key == pygame.K_p:  # 按 P 暂停游戏
                        self.pause_game()

            # 检查是否撞墙
            if x1 >= self.display_width or x1 < 0 or y1 >= self.display_height or y1 < 0:
                game_over = True
                break  # 立即退出循环

            # 更新蛇的位置
            x1 += x1_change
            y1 += y1_change
            self.dis.fill(self.white)

            # 绘制网格线
            self.draw_grid()

            # 绘制普通果实
            for foodx, foody in normal_foods:
                pygame.draw.rect(self.dis, self.red, [foodx, foody, self.snake_block, self.snake_block])

            # 绘制特殊果实
            for special_food in special_foods:
                fx, fy, ftype = special_food
                if ftype == "green":
                    pygame.draw.rect(self.dis, self.green, [fx, fy, self.snake_block, self.snake_block])
                elif ftype == "blue":
                    pygame.draw.rect(self.dis, self.blue, [fx, fy, self.snake_block, self.snake_block])
                elif ftype == "orange":
                    pygame.draw.rect(self.dis, self.orange, [fx, fy, self.snake_block, self.snake_block])
                elif ftype == "rainbow":
                    pygame.draw.rect(self.dis, self.rainbow, [fx, fy, self.snake_block, self.snake_block])

            # 绘制紫色果实
            for fx, fy in purple_foods:
                pygame.draw.rect(self.dis, self.purple, [fx, fy, self.snake_block, self.snake_block])

            # 紫色果实生成逻辑
            if Length_of_snake - 1 >= 30:  # 分数达到30后开始生成
                purple_food_timer += 1
                if purple_food_timer >= 20:  # 每两秒生成一次
                    chance = random.randint(1, 100)
                    count = 1 if chance <= 90 else (2 if chance <= 95 else 3)
                    for _ in range(count):
                        purple_foods.append(self.generate_purple_food(snake_List))
                    purple_food_timer = 0

            # 紫色果实移动逻辑
            purple_foods, game_over = self.handle_purple_food(purple_foods, snake_List, normal_foods, x1, y1)
            if game_over:
                break

            # 更新蛇的身体
            snake_Head = [x1, y1]
            snake_List.append(snake_Head)

            # 如果蛇的长度超过当前长度，移除尾部
            if len(snake_List) > Length_of_snake:
                del snake_List[0]

            # 检查是否撞到自己
            for x in snake_List[:-1]:
                if x == snake_Head:
                    game_over = True
                    break

            # 绘制蛇和分数
            self.our_snake(self.snake_block, snake_List)
            self.your_score(Length_of_snake - 1)

            # 显示技能倒计时
            if speed_timer > 0:
                speed_timer -= 1
                remaining_time = speed_timer // 10  # 假设帧率为 10
                countdown_text = self.font_style.render(f"Skill Time Left: {remaining_time}s", True, self.black)
                self.dis.blit(countdown_text, [self.display_width - 200, 10])  # 第二行右上角显示倒计时
            elif snake_speed != default_snake_speed:
                snake_speed = default_snake_speed  # 恢复默认速度

            pygame.display.update()

            # 检查是否吃到普通果实
            for food in normal_foods[:]:
                foodx, foody = food
                if x1 == foodx and y1 == foody:
                    normal_foods.remove(food)
                    Length_of_snake += 1

            # 检查是否吃到特殊果实
            for special_food in special_foods[:]:
                fx, fy, ftype = special_food
                if x1 == fx and y1 == fy:
                    special_foods.remove(special_food)
                    if ftype == "green":  # 加速果实
                        Length_of_snake += 1
                        snake_speed = 15
                        speed_timer = 100
                    elif ftype == "blue":  # 减速果实
                        Length_of_snake += 1
                        snake_speed = 5
                        speed_timer = 100
                    elif ftype == "orange":  # 橙色果实
                        Length_of_snake += 2
                    elif ftype == "rainbow":  # 彩色果实
                        Length_of_snake += 5  # 增加分数
                        normal_foods.clear()  # 清除所有普通果实
                        special_foods.clear()  # 清除所有特殊果实

            # 控制普通果实生成
            if len(normal_foods) < 5:  # 限制普通果实最多存在 5 个
                normal_food_timer += 1
                if normal_food_timer >= 20:  # 假设帧率为 10，每两秒生成一个普通果实
                    normal_foods.append(self.generate_food(snake_List))
                    normal_food_timer = 0

            # 控制特殊果实生成
            current_score = Length_of_snake - 1
            if current_score // 10 > last_special_food_score // 10:  # 分数每增加 10 时生成特殊果实
                for _ in range(2):  # 生成两个特殊果实
                    fx, fy = self.generate_food(snake_List)
                    ftype = random.choice(["green", "blue", "orange", "rainbow"])
                    special_foods.append((fx, fy, ftype))
                last_special_food_score = current_score

            # 控制游戏速度
            self.clock.tick(snake_speed)

        # 进入结束页面
        self.game_over_screen(Length_of_snake - 1)


if __name__ == "__main__":
    game = SnakeGame()
    game.gameLoop()